﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Security.Cryptography;
using System.Web;
using Eacademy.Domain.Models;
using Eacademy.Library.Helpers;
using System.Text;
using SubSonic.Extensions;
using System.Data;
using System.Web.Mvc;
using System.Web.UI;
using System.IO;


//:P
public static class ExtensionMethodsHelper
{

    public static string ToDelimitedString(this DataTable dataTable, string columnName, string delimeter = ",")
    {
        var courseIdList = dataTable.Rows.Cast<DataRow>().Select(row => row[columnName].ToString()).ToList();

        return String.Join(delimeter, courseIdList);
    }

    public static string ToDelimitedString<T>(this IList<T> list, string delimeter = ",")
    {
        return String.Join(delimeter, list);
    }

    public static DateTime ToDate(this object date)
    {
        return Convert.ToDateTime(date);
    }

    public static int ToInteger(this object num)
    {
        return Convert.ToInt32(num);
    }

    public static long ToLong(this object num)
    {
        return Convert.ToInt64(num);
    }

    public static bool ToBooleaan(this object num)
    {
        return Convert.ToBoolean(num);

    }

    /// <summary>
    /// Determines whether a collection is null or has no elements without having to enumerate the entire collection to get a count.  Uses LINQ.
    /// </summary>
    /// <typeparam name="T">The item type.</typeparam>
    /// <param name="items">The items.</param>
    /// <returns>
    /// <c>true</c> if this list is null or empty; otherwise, <c>false</c>.
    /// </returns>
    public static bool IsNullOrEmpty<T>(this IList<T> items)
    {
        return items == null || !items.Any();
    }

    public static bool IsNullOrEmpty(this DataTable dataTable)
    {
        return !(dataTable.Rows.Count > 0);
    }

    public static string Truncate(this string s, int maxLength)
    {
        if (string.IsNullOrEmpty(s) || maxLength <= 0)
            return string.Empty;
        else if (s.Length > maxLength)
            return s.Substring(0, maxLength) + "...";
        else
            return s;
    }

    // IsNumeric Function
    public static bool IsNumeric(this string expression)
    {
        // Variable to collect the Return value of the TryParse method.
        bool isNum;

        // Define variable to collect out parameter of the TryParse method. If the conversion fails, the out parameter is zero.
        double retNum;

        // The TryParse method converts a string in a specified style and culture-specific format to its double-precision floating point number equivalent.
        // The TryParse method does not generate an exception if the conversion fails. If the conversion passes, True is returned. If it does not, False is returned.
        isNum = Double.TryParse(expression, System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
        return isNum;
    }

    public static string GenerateCountQuery(this string selectString)
    {
        selectString = selectString.RemoveBetween(Constants.StartRemoveTag, Constants.EndRemoveTag);
        StringBuilder countString = new StringBuilder();
        countString.AppendLine(@" SELECT COUNT(*) as count ");
        countString.Append(selectString);
        return countString.ToString();
    }

    public static void AddStartRemove(this StringBuilder str)
    {
        str.AppendLine(Constants.StartRemoveTag);
    }

    public static void AddEndRemove(this StringBuilder str)
    {
        str.AppendLine(Constants.EndRemoveTag);
    }

    public static string ToMySqlDate(this DateTime date)
    {
        return (date.ToString("yyyy-MM-dd HH:mm:ss"));
    }

    public static string GetMonthName(this int month)
    {
        DateTime date = new DateTime(1900, month, 1);
        return date.ToString("MMM");
    }

}

public static class ListExtentsions {
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach (var item in collection) action(item);
        return collection;
    }

    public static SelectList ToSelectList<T>(this IEnumerable<T> collection)
    {
        return new SelectList(collection, "Key", "Value");
    }

    public static SelectList ToSelectList<T>(this IEnumerable<T> collection, string selectedValue)
    {
        return new SelectList(collection, "Key", "Value", selectedValue);
    }

    public static SelectList ToSelectList<T>(this IEnumerable<T> collection,
                         string dataValueField, string dataTextField)
    {
        return new SelectList(collection, dataValueField, dataTextField);
    }

    public static SelectList ToSelectList<T>(this IEnumerable<T> collection,
                         string dataValueField, string dataTextField, string selectedValue)
    {
        return new SelectList(collection, dataValueField, dataTextField, selectedValue);
    }


    public static void Shuffle<T>(this IList<T> list)
    {
        using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider())
        {
            int n = list.Count;
            while (n > 1)
            {
                byte[] box = new byte[1];
                do
                    provider.GetBytes(box);
                while (!(box[0] < n * (Byte.MaxValue / n)));
                int k = (box[0] % n);
                n--;
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }

    public static void Shuffle<T>(this IList<T> list, out List<int> seed)
    {
        seed = new List<int>();
        using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider())
        {
            int n = list.Count;
            while (n > 1)
            {
                byte[] box = new byte[1];
                do
                    provider.GetBytes(box);
                while (!(box[0] < n * (Byte.MaxValue / n)));
                seed.Add(box[0].ToInteger());
                int k = (box[0] % n);
                n--;
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }

    public static void Shuffle<T>(this IList<T> list, List<int> seed)
    {
        using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider())
        {
            int seedIndex = 0;
            int n = list.Count;
            while (n > 1)
            {
                int box = seed[seedIndex++];
                int k = (box % n);
                n--;
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }



}

public static class RenderPartialExtensions
{

    public static string RenderPartialToString(string controlName, object viewData)
    {


        ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };

        viewPage.ViewData = new ViewDataDictionary(viewData);
        viewPage.Controls.Add(viewPage.LoadControl(controlName));

        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter tw = new HtmlTextWriter(sw))
            {
                viewPage.RenderControl(tw);
            }
        }

        return sb.ToString();
    }
}
